package com.wy.office.swift.word.handler;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.poi.xwpf.usermodel.Document;
import org.apache.poi.xwpf.usermodel.PositionInParagraph;
import org.apache.poi.xwpf.usermodel.TextSegment;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFFooter;
import org.apache.poi.xwpf.usermodel.XWPFHeader;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableCell.XWPFVertAlign;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;
import org.apache.xmlbeans.XmlObject;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHighlight;

import com.wy.office.swift.exception.OfficeSwiftException;
import com.wy.office.swift.exception.ParamNecessaryException;
import com.wy.office.swift.util.CollectionUtils;
import com.wy.office.swift.util.StringUtils;
import com.wy.office.swift.word.model.WordForModel;
import com.wy.office.swift.word.model.WordParamModel;

/**
 * docx处理
 * 
 * @author wangyuan
 * @since 2018年7月13日
 */
public class XWPFWordHandler extends AWordHandler {

	@Override
	public List<String> extractVariablesFromSourceFile(String sourcePathName) throws OfficeSwiftException {
		// 参数验证
		if (StringUtils.checkParamIsEmpty(sourcePathName)) {
			throw new ParamNecessaryException("sourcePathName can not be null or empty.");
		}

		List<String> variables = new ArrayList<>();
		InputStream in = null;
		XWPFDocument doc = null;
		try {
			in = new FileInputStream(sourcePathName);
			doc = new XWPFDocument(in);

			// 临时存放变量容器
			Set<String> variableSet = new HashSet<>();

			// 页眉
			List<XWPFHeader> headers = doc.getHeaderList();
			if (CollectionUtils.isNotEmpty(headers)) {
				for (XWPFHeader header : headers) {
					// 段落中变量的提取
					List<XWPFParagraph> paragraphs = header.getParagraphs();
					variableSet.addAll(extractVariablesFromParagraph(paragraphs));

					// 表格中变量的提取
					List<XWPFTable> tables = header.getTables();
					variableSet.addAll(extractVariablesFromTable(tables));
				}
			}

			// 页脚
			List<XWPFFooter> footers = doc.getFooterList();
			if (CollectionUtils.isNotEmpty(footers)) {
				for (XWPFFooter footer : footers) {
					// 段落中变量的提取
					List<XWPFParagraph> paragraphs = footer.getParagraphs();
					variableSet.addAll(extractVariablesFromParagraph(paragraphs));

					// 表格中变量的提取
					List<XWPFTable> tables = footer.getTables();
					variableSet.addAll(extractVariablesFromTable(tables));
				}
			}

			// 段落中变量的提取
			List<XWPFParagraph> paragraphs = doc.getParagraphs();
			variableSet.addAll(extractVariablesFromParagraph(paragraphs));

			// 表格中变量的提取
			List<XWPFTable> tables = doc.getTables();
			variableSet.addAll(extractVariablesFromTable(tables));

			variables.addAll(variableSet);
		} catch (Exception e) {
			throw new OfficeSwiftException("参数提取错误", e);
		} finally {
			closeResource(doc);
			closeResource(in);
		}

		return variables;
	}

	@Override
	public void dealOfficeWord(String sourcePathName, String targetPathName, WordParamModel param)
			throws OfficeSwiftException {
		// 参数验证
		if (StringUtils.checkParamIsEmpty(sourcePathName, targetPathName)) {
			throw new ParamNecessaryException("sourcePathName or targetPathName can not be null or empty.");
		}

		if (param == null) {
			param = new WordParamModel();
		}

		OutputStream out = null;
		try {
			ByteArrayOutputStream resultOut = dealOfficeWord(sourcePathName, param);
			// 写入新的文件
			File newFile = new File(targetPathName);
			out = new FileOutputStream(newFile);
			resultOut.writeTo(out);
		} catch (Exception e) {
			throw new OfficeSwiftException(e);
		} finally {
			closeResource(out);
		}
	}

	@Override
	public ByteArrayOutputStream dealOfficeWord(String sourcePathName, WordParamModel param)
			throws OfficeSwiftException {
	    // 参数验证
        if (StringUtils.checkParamIsEmpty(sourcePathName)) {
            throw new ParamNecessaryException("sourcePathName can not be null or empty.");
        }

        if (param == null) {
            param = new WordParamModel();
        }

        ByteArrayOutputStream out = null;
        InputStream in = null;
        XWPFDocument doc = null;
        try {
            in = new FileInputStream(sourcePathName);
            doc = new XWPFDocument(in);
            dealOfficeWord(doc, param);

            // 写入到字节流中
            out = new ByteArrayOutputStream();
            doc.write(out);
        } catch (Exception e) {
            throw new OfficeSwiftException(e);
        } finally {
            closeResource(doc);
            closeResource(in);
        }
        
        return out;
	}

	@Override
    public Document dealOfficeWord(Document document, WordParamModel param) throws OfficeSwiftException {
        // 参数验证
        if (document == null) {
            throw new ParamNecessaryException("doc can not be null.");
        }

        if (param == null) {
            param = new WordParamModel();
        }
        
        XWPFDocument doc = null;
        try {
            doc = (XWPFDocument) document;
            
            //For循环结构处理（填充变量值）
            if(!param.isEmptyOfForParams()){
                //结构解析
                parseForStructure(doc, param);
                //键值对解析
                param.parseForParams();
            }

            // 页眉
            List<XWPFHeader> headers = doc.getHeaderList();
            if (CollectionUtils.isNotEmpty(headers)) {
                for (XWPFHeader header : headers) {
                    // 段落中文本处理
                    List<XWPFParagraph> paragraphs = header.getParagraphs();
                    replaceParamsOfMoreText(paragraphs, param.getSimpleParams());

                    // 表格中文本处理
                    List<XWPFTable> tables = header.getTables();
                    replaceParamsOfTable(tables, param.getSimpleParams());
                }
            }

            // 页脚
            List<XWPFFooter> footers = doc.getFooterList();
            if (CollectionUtils.isNotEmpty(footers)) {
                for (XWPFFooter footer : footers) {
                    // 段落中文本处理
                    List<XWPFParagraph> paragraphs = footer.getParagraphs();
                    replaceParamsOfMoreText(paragraphs, param.getSimpleParams());

                    // 表格中文本处理
                    List<XWPFTable> tables = footer.getTables();
                    replaceParamsOfTable(tables, param.getSimpleParams());
                }
            }

            // 段落中文本处理
            List<XWPFParagraph> paragraphs = doc.getParagraphs();
            replaceParamsOfMoreText(paragraphs, param.getSimpleParams());

            // 表格中文本处理
            List<XWPFTable> tables = doc.getTables();
            replaceParamsOfTable(tables, param.getSimpleParams());
        } catch (Exception e) {
            throw new OfficeSwiftException(e);
        }
        
        return document;
    }

    @Override
    public Document mergeDocment(Document source, Document target) throws OfficeSwiftException {
    	XWPFDocument sourceDoc = null;
        XWPFDocument targetDoc = null;
        XWPFDocument resultDoc = null;
        try {
            sourceDoc = (XWPFDocument) source;
            targetDoc = (XWPFDocument) target;
            resultDoc = new XWPFDocument();
            
            XWPFParagraph sourceParagraph = sourceDoc.createParagraph();
            
            //设置分页符
            sourceParagraph.setPageBreak(true);
            
            CTBody sourceBody = sourceDoc.getDocument().getBody();
            CTBody targetBody = targetDoc.getDocument().getBody();
            
            String targetText = targetBody.xmlText();
            String sourceText = sourceBody.xmlText();
            String prefixText = sourceText.substring(0, sourceText.indexOf(">") + 1);
            String mainText = sourceText.substring(sourceText.indexOf(">") + 1, sourceText.lastIndexOf("<"));
            String sufixText = sourceText.substring( sourceText.lastIndexOf("<"));
            String apendText = targetText.substring(targetText.indexOf(">") + 1, targetText.lastIndexOf("<"));
            CTBody makeBody = CTBody.Factory.parse(prefixText + mainText + apendText + sufixText);
            XmlObject newObj = sourceBody.set(makeBody);
            resultDoc.getDocument().setBody((CTBody) newObj);
        } catch (Exception e) {
            throw new OfficeSwiftException(e);
        }
        
        return resultDoc;
    }

    /**
     * 从Paragraph中提取变量
     * @param paragraphs
     * @return
     * @throws OfficeSwiftException
     */
    private List<String> extractVariablesFromParagraph(List<XWPFParagraph> paragraphs) throws OfficeSwiftException {
		List<String> result = new ArrayList<>();
		if (CollectionUtils.isEmpty(paragraphs)) {
			return result;
		}

		// 临时存放变量容器
		Set<String> variableSet = new HashSet<>();
		for (XWPFParagraph paragraph : paragraphs) {
			variableSet.addAll(extractVariables(paragraph.getText()));
		}

		result.addAll(variableSet);

		return result;
	}

    /**
     * 从Table中提取变量
     * @param tables
     * @return
     * @throws OfficeSwiftException
     */
	private List<String> extractVariablesFromTable(List<XWPFTable> tables) throws OfficeSwiftException {
		List<String> result = new ArrayList<>();
		if (CollectionUtils.isEmpty(tables)) {
			return result;
		}

		// 临时存放变量容器
		Set<String> variableSet = new HashSet<>();
		for (XWPFTable table : tables) {
			int rowCount = table.getNumberOfRows();
			for (int i = 0; i < rowCount; i++) {
				XWPFTableRow tableRow = table.getRow(i);
				List<XWPFTableCell> tableCells = tableRow.getTableCells();
				for (XWPFTableCell cellItem : tableCells) {
					// 单元格中文本处理
					List<XWPFParagraph> itemParagraphs = cellItem.getParagraphs();
					variableSet.addAll(extractVariablesFromParagraph(itemParagraphs));

					// 单元格中表格处理
					List<XWPFTable> itemTables = cellItem.getTables();
					variableSet.addAll(extractVariablesFromTable(itemTables));
				}
			}
		}

		result.addAll(variableSet);

		return result;
	}

	/**
	 * 替换table中的变量为指定的值
	 * @param tables
	 * @param replaceParams
	 * @throws OfficeSwiftException
	 */
	private void replaceParamsOfTable(List<XWPFTable> tables, Map<String, String> replaceParams) throws OfficeSwiftException {
		if (CollectionUtils.isEmpty(tables) || CollectionUtils.isEmpty(replaceParams)) {
			return;
		}

		for (XWPFTable table : tables) {
			int rowCount = table.getNumberOfRows();
			for (int i = 0; i < rowCount; i++) {
				XWPFTableRow tableRow = table.getRow(i);
				List<XWPFTableCell> tableCells = tableRow.getTableCells();
				for (XWPFTableCell cellItem : tableCells) {
					// 单元格中文本处理
					List<XWPFParagraph> itemParagraphs = cellItem.getParagraphs();
					replaceParamsOfMoreText(itemParagraphs, replaceParams);

					// 单元格中表格处理
					List<XWPFTable> itemTables = cellItem.getTables();
					replaceParamsOfTable(itemTables, replaceParams);
				}
			}
		}
	}

	/**
	 * 替换多text结构中的变量为指定的值
	 * @param paragraphs
	 * @param replaceParams
	 * @throws OfficeSwiftException
	 */
	private void replaceParamsOfMoreText(List<XWPFParagraph> paragraphs, Map<String, String> replaceParams)
			throws OfficeSwiftException {
		if (CollectionUtils.isEmpty(paragraphs) || CollectionUtils.isEmpty(replaceParams)) {
			return;
		}

		for (XWPFParagraph paragraph : paragraphs) {
			replaceParamsOfSingleText(paragraph, replaceParams);
		}
	}

	/**
	 * 替换单个text结构中的变量为指定的值
	 * @param paragraph
	 * @param replaceParams
	 * @throws OfficeSwiftException
	 */
	private void replaceParamsOfSingleText(XWPFParagraph paragraph, Map<String, String> replaceParams)
			throws OfficeSwiftException {
		if (paragraph == null || CollectionUtils.isEmpty(replaceParams)) {
			return;
		}

		List<XWPFRun> runs = paragraph.getRuns();
		for (Entry<String, String> item : replaceParams.entrySet()) {
			String searchText = VARIABLE_PREFIX + item.getKey() + VARIABLE_SUFFIX;
			String replaceText = StringUtils.isEmpty(item.getValue()) ? "" : item.getValue();

			// 不能有$${val}的这种情况存在，否则会匹配不到
			TextSegment segement = paragraph.searchText(searchText, new PositionInParagraph());
			if (segement == null) {
				continue;
			}

			// 情况一：beginRun与endRun相等
			if (segement.getBeginRun() == segement.getEndRun()) {
				XWPFRun run = runs.get(segement.getBeginRun());
				String text = run.text();
				// TODO 多个值的替换
				// text = text.replaceAll(searchText, replaceText);
				text = text.replace(searchText, replaceText);

				run.setText(text, 0);
			}

			// 情况二：beginRun与endRun相差等于1
			if (segement.getEndRun() - segement.getBeginRun() == 1) {
				XWPFRun beginRun = runs.get(segement.getBeginRun());
				XWPFRun endRun = runs.get(segement.getEndRun());

				String beginRunText = beginRun.text();
				String endRunText = endRun.text();

				// start处理
				int lastIndexOf = beginRunText.lastIndexOf(VARIABLE_PREFIX_FIRST_WORD);

				beginRunText = beginRunText.substring(0, lastIndexOf);

				// 拼接替换字符，以第一个Run为准
				beginRunText = beginRunText + replaceText;

				beginRun.setText(beginRunText, 0);

				// end处理
				int indexOf = endRunText.indexOf(VARIABLE_SUFFIX);

				endRunText = endRunText.substring(indexOf + 1, endRunText.length());
				endRun.setText(endRunText, 0);
			}

			// 情况三：beginRun与endRun相差大于1
			if (segement.getEndRun() - segement.getBeginRun() > 1) {
				XWPFRun beginRun = runs.get(segement.getBeginRun());
				XWPFRun endRun = runs.get(segement.getEndRun());

				String beginRunText = beginRun.text();
				String endRunText = endRun.text();

				// start处理
				int lastIndexOf = beginRunText.lastIndexOf(VARIABLE_PREFIX_FIRST_WORD);

				beginRunText = beginRunText.substring(0, lastIndexOf);

				// 拼接替换字符，以第一个Run为准
				beginRunText = beginRunText + replaceText;

				beginRun.setText(beginRunText, 0);

				// end处理
				int indexOf = endRunText.indexOf(VARIABLE_SUFFIX);

				endRunText = endRunText.substring(indexOf + 1, endRunText.length());
				endRun.setText(endRunText, 0);

				for (int i = segement.getEndRun() - 1; i > segement.getBeginRun(); i--) {
					paragraph.removeRun(i);
				}
			}
		}
	}
	
	/**
	 * 解析document中的For结构
	 * @param doc
	 * @param param
	 */
	private void parseForStructure(XWPFDocument doc, WordParamModel param) {
	    // 页眉
        List<XWPFHeader> headers = doc.getHeaderList();
        if (CollectionUtils.isNotEmpty(headers)) {
            for (XWPFHeader header : headers) {
                // 段落中For结构处理
                List<XWPFParagraph> paragraphs = header.getParagraphs();
                parseForStructureOfMoreText(paragraphs, param);

                // 表格中For结构处理
                List<XWPFTable> tables = header.getTables();
                parseForStructureOfMoreTable(tables, param);
            }
        }

        // 页脚
        List<XWPFFooter> footers = doc.getFooterList();
        if (CollectionUtils.isNotEmpty(footers)) {
            for (XWPFFooter footer : footers) {
                // 段落中For结构处理
                List<XWPFParagraph> paragraphs = footer.getParagraphs();
                parseForStructureOfMoreText(paragraphs, param);

                // 表格中For结构处理
                List<XWPFTable> tables = footer.getTables();
                parseForStructureOfMoreTable(tables, param);
            }
        }

        // 段落中For结构处理
        List<XWPFParagraph> paragraphs = doc.getParagraphs();
        parseForStructureOfMoreText(paragraphs, param);

        // 表格中For结构处理
        List<XWPFTable> tables = doc.getTables();
        parseForStructureOfMoreTable(tables, param);
    }
	
	/**
	 * 针对document中的所有table解析for循环结构
	 * @param tables
	 * @param param
	 */
	private void parseForStructureOfMoreTable(List<XWPFTable> tables, WordParamModel param) {
	    if (CollectionUtils.isEmpty(tables) || param.isEmptyOfForParams()) {
            return;
        }
	    
	    for (XWPFTable table : tables) {
	    	while(parseForStructureOfSingleTable(table, param)) {}
        }
	}
	
	/**
	 * 针对单个table解析for循环结构
	 * @param table
	 * @param param
	 * @return
	 */
	private boolean parseForStructureOfSingleTable(XWPFTable table, WordParamModel param) {
        for (int i = 0; i < table.getNumberOfRows(); i++) {
            XWPFTableRow tableRow = table.getRow(i);
            List<XWPFTableCell> tableCells = tableRow.getTableCells();
            for (int j = 0;j < tableCells.size();j++) {
            	XWPFTableCell tableCell = tableCells.get(j);
            	//匹配每个单元格内是否存在符合for循环变量
                List<XWPFParagraph> paragraphs = tableCell.getParagraphs();
                for(XWPFParagraph paragraphItem : paragraphs){
                	for(WordForModel forModelItem : param.getForParams()) {
                		//循环主体非表格，则不做处理
                		if(!FOR_SUBJECT_TABLE.equals(forModelItem.getSubject())) {
                			continue;
                		}
                		
                		List<String> searchTexts = forModelItem.getSearchText();
                		TextSegment segement = null;
                		for(String searchTextItem : searchTexts) {
                			segement = paragraphItem.searchText(searchTextItem, new PositionInParagraph());
                    		if (segement != null) {
                    			//存在循环体
                    			if(FOR_WAY_ROW.equals(forModelItem.getWay())) {
                    				//行循环体
                    				parseRowForStructureOfTable(table, forModelItem, i);
                    			}
                    			if(FOR_WAY_CELL.equals(forModelItem.getWay())) {
                    				//列循环体
                    				parseCellForStructureOfTable(table, forModelItem, j);
                    			}
                    			return true;
                    		}
                		}
                	}
                }
            }
        }
        
        return false;
	}
	
	/**
	 * table中单行循环处理
	 * @param table
	 * @param forModel
	 * @param rowIndex
	 */
	private void parseRowForStructureOfTable(XWPFTable table, WordForModel forModel, int rowIndex) {
		XWPFTableRow originTableRow = table.getRow(rowIndex);
		//当循环体中无数据时的处理
		if(forModel.dataSize() == 0) {
			Map<String, String> replaceParams = forModel.getKeyReplaceParam(-1);
			for(XWPFTableCell cellItem : originTableRow.getTableCells()) {
				replaceParamsOfMoreText(cellItem.getParagraphs(), replaceParams);
			}
			return;
		}
		
		XWPFTableRow newTableRow = null;
		Map<String, String> replaceParams = null;
		for(int i = 1;i < forModel.dataSize();i++) {
		    //添加新行
			newTableRow = table.insertNewTableRow(rowIndex + 1);
			copyXWPFTableRow(originTableRow, newTableRow);
			
			//新行中列的复制处理
			XWPFTableCell originCell = null;
			XWPFTableCell newCell = null;
			for(int j = 0;j < originTableRow.getTableCells().size();j++) {
				originCell = originTableRow.getTableCells().get(j);
				newCell = newTableRow.addNewTableCell();//添加新列
				
				copyXWPFTableCell(originCell, newCell);
				
				//新列中的文本处理
				XWPFParagraph originParagraph = null;
				XWPFParagraph newParagraph = null;
				for(int w = 0; w < originCell.getParagraphs().size();w++) {
					originParagraph = originCell.getParagraphs().get(w);
					if(w < newCell.getParagraphs().size()) {
						newParagraph = newCell.getParagraphs().get(w);
					} else {
						newParagraph = newCell.addParagraph();
					}
					copyXWPFParagraph(originParagraph, newParagraph);
					
					XWPFRun newRun = null;
					XWPFRun originRun = null;
					for(int q = 0; q < originParagraph.getRuns().size();q++) {
					    originRun = originParagraph.getRuns().get(q);
					    if(q < newParagraph.getRuns().size()) {
					        newRun = newParagraph.getRuns().get(q);
	                    } else {
	                        newRun = newParagraph.createRun();
	                    }
						copyXWPFRun(originRun, newRun);
					}
				}
			}
			
			//替换此行中的变量名称
			replaceParams = forModel.getKeyReplaceParam(i);
			for(XWPFTableCell cellItem : newTableRow.getTableCells()) {
				replaceParamsOfMoreText(cellItem.getParagraphs(), replaceParams);
			}
		}
		
		//替换原始行变量名称
		replaceParams = forModel.getKeyReplaceParam(0);
		for(XWPFTableCell cellItem : originTableRow.getTableCells()) {
			replaceParamsOfMoreText(cellItem.getParagraphs(), replaceParams);
		}
	}
	
	/**
	 * 复制XWPFTableRow属性，从source到target
	 * @param source
	 * @param target
	 */
	private void copyXWPFTableRow(XWPFTableRow source, XWPFTableRow target) {
	    target.setHeight(source.getHeight());
	    target.setCantSplitRow(source.isCantSplitRow());
	    target.setRepeatHeader(source.isRepeatHeader());
	}
	
	/**
	 * 复制XWPFTableCell属性，从source到target
	 * @param source
	 * @param target
	 */
	private void copyXWPFTableCell(XWPFTableCell source, XWPFTableCell target) {
	    target.setColor(source.getColor());
	    XWPFVertAlign alignment = source.getVerticalAlignment();
	    if(alignment != null) {
	    	target.setVerticalAlignment(alignment);
	    }
	}
	
	/**
	 * 复制XWPFParagraph属性，从source到target
	 * @param source
	 * @param target
	 */
	private void copyXWPFParagraph(XWPFParagraph source, XWPFParagraph target) {
	    target.setNumID(source.getNumID());
	    //target.setNumILvl(source.getNumIlvl());
	    target.setKeepNext(source.isKeepNext());
	    target.setAlignment(source.getAlignment());
	    target.setFontAlignment(source.getFontAlignment());
	    target.setVerticalAlignment(source.getVerticalAlignment());
	    target.setBorderTop(source.getBorderTop());
	    target.setBorderBottom(source.getBorderBottom());
	    target.setBorderLeft(source.getBorderLeft());
	    target.setBorderRight(source.getBorderRight());
	    target.setBorderBetween(source.getBorderBetween());
	    target.setPageBreak(source.isPageBreak());
	    target.setSpacingAfter(source.getSpacingAfter());
        //下面1项设置，office 2010打开文档会有问题
        //target.setSpacingAfterLines(source.getSpacingAfterLines());
	    target.setSpacingBefore(source.getSpacingBefore());
        //下面1项设置，office 2010打开文档会有问题
        //target.setSpacingBeforeLines(source.getSpacingBeforeLines());
	    target.setSpacingLineRule(source.getSpacingLineRule());
	    target.setSpacingBetween(source.getSpacingBetween());
	    target.setIndentationLeft(source.getIndentationLeft());
	    target.setIndentationRight(source.getIndentationRight());
	    target.setIndentationHanging(source.getIndentationHanging());
	    target.setIndentationFirstLine(source.getIndentationFirstLine());
	    target.setIndentFromLeft(source.getIndentFromLeft());
	    target.setIndentFromRight(source.getIndentFromRight());
	    target.setFirstLineIndent(source.getFirstLineIndent());
        //下面2项设置，下面两项设置会抛异常
        //target.setWordWrapped(source.isWordWrapped());
        //target.setWordWrap(source.isWordWrap());
	    target.setStyle(source.getStyle());
	}
	
	/**
	 * 复制XWPFRun属性，从source到target
	 * @param source
	 * @param target
	 */
	@SuppressWarnings("deprecation")
    private void copyXWPFRun(XWPFRun source, XWPFRun target) {
	    target.setBold(source.isBold());
	    target.setColor(source.getColor());
	    target.setText(source.text());
	    target.setItalic(source.isItalic());
	    target.setUnderline(source.getUnderline());
	    target.setStrikeThrough(source.isStrikeThrough());
	    target.setStrike(source.isStrike());
	    target.setDoubleStrikethrough(source.isDoubleStrikeThrough());
	    target.setSmallCaps(source.isSmallCaps());
	    target.setCapitalized(source.isCapitalized());
	    target.setShadow(source.isShadowed());
	    target.setImprinted(source.isImprinted());
	    target.setEmbossed(source.isEmbossed());
	    target.setVerticalAlignment(source.getVerticalAlignment().toString());
	    target.setKerning(source.getKerning());
	    if(source.getCTR().getRPr() != null){
	    	CTHighlight highlight = source.getCTR().getRPr().getHighlight();
	    	if(highlight != null) {
	    		target.getCTR().getRPr().setHighlight((CTHighlight) highlight.copy());
	    	}
	    }
	    target.setCharacterSpacing(source.getCharacterSpacing());
	    if(source.getFontFamily() != null) {
	    	target.setFontFamily(source.getFontFamily());
	    }
	    if(source.getFontSize() != -1) {
	    	target.setFontSize(source.getFontSize());
	    }
	    target.setTextPosition(source.getTextPosition());
	}
	
	/**
	 * table中单列循环处理
	 * @param table
	 * @param forModel
	 * @param cellIndex
	 */
	private void parseCellForStructureOfTable(XWPFTable table, WordForModel forModel, int cellIndex) {
		//TODO
	}
	
	private void parseForStructureOfMoreText(List<XWPFParagraph> paragraphs, WordParamModel param) {
        //TODO
    }
}
